package cn.iocoder.yudao.module.promotion.service.quickcombinationactivity;

import cn.hutool.core.util.ObjUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
import cn.iocoder.yudao.module.promotion.controller.admin.combination.vo.product.CombinationProductBaseVO;
import cn.iocoder.yudao.module.promotion.controller.admin.quickcombinationactivity.vo.product.QuickCombinationProductBaseVO;
import cn.iocoder.yudao.module.promotion.convert.combination.CombinationActivityConvert;
import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationActivityDO;
import cn.iocoder.yudao.module.promotion.dal.dataobject.combination.CombinationProductDO;
import cn.iocoder.yudao.module.promotion.dal.dataobject.quickcombinationactivity.QuickCombinationProductDO;
import cn.iocoder.yudao.module.promotion.dal.mysql.quickcombinationactivity.QuickCombinationProductMapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;

import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import java.util.*;
import cn.iocoder.yudao.module.promotion.controller.admin.quickcombinationactivity.vo.*;
import cn.iocoder.yudao.module.promotion.dal.dataobject.quickcombinationactivity.QuickCombinationActivityDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;

import cn.iocoder.yudao.module.promotion.convert.quickcombinationactivity.QuickCombinationActivityConvert;
import cn.iocoder.yudao.module.promotion.dal.mysql.quickcombinationactivity.QuickCombinationActivityMapper;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.afterNow;
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.beforeNow;
import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SKU_NOT_EXISTS;
import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS;
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
import static java.util.Collections.singletonList;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;

/**
 * 进货活动 Service 实现类
 *
 * @author 曹建伟
 */
@Service
@Validated
public class QuickCombinationActivityServiceImpl implements QuickCombinationActivityService {

    @Resource
    private QuickCombinationActivityMapper quickCombinationActivityMapper;

    @Resource
    private QuickCombinationProductMapper quickCombinationProductMapper;

    @Resource
    private ProductSpuApi productSpuApi;
    @Resource
    private ProductSkuApi productSkuApi;

    /**
     * 校验拼团商品是否都存在
     *
     * @param spuId    商品 SPU 编号
     * @param products 拼团商品
     */
    private void validateProductExists(Long spuId, List<QuickCombinationProductBaseVO> products) {
        // 1. 校验商品 spu 是否存在
        ProductSpuRespDTO spu = productSpuApi.getSpu(spuId);
        if (spu == null) {
            throw exception(SPU_NOT_EXISTS);
        }

        // 2. 校验商品 sku 都存在
        List<ProductSkuRespDTO> skus = productSkuApi.getSkuListBySpuId(singletonList(spuId));
        Map<Long, ProductSkuRespDTO> skuMap = convertMap(skus, ProductSkuRespDTO::getId);
        products.forEach(product -> {
            if (!skuMap.containsKey(product.getSkuId())) {
                throw exception(SKU_NOT_EXISTS);
            }
        });
    }

    @Override
    public Long createQuickCombinationActivity(QuickCombinationActivityCreateReqVO createReqVO) {

        // 校验商品是否存在
        validateProductExists(createReqVO.getSpuId(), createReqVO.getProducts());

        // 插入拼团活动
        QuickCombinationActivityDO activity = QuickCombinationActivityConvert.INSTANCE.convert(createReqVO)
                .setStatus(0);
        quickCombinationActivityMapper.insert(activity);
        // 插入商品
        List<QuickCombinationProductDO> products = QuickCombinationActivityConvert.INSTANCE.convertList(createReqVO.getProducts(), activity);
        quickCombinationProductMapper.insertBatch(products);
        return activity.getId();
    }

    @Override
    public void updateQuickCombinationActivity(QuickCombinationActivityUpdateReqVO updateReqVO) {
        // 校验存在
        validateQuickCombinationActivityExists(updateReqVO.getId());
        // 更新
        QuickCombinationActivityDO updateObj = QuickCombinationActivityConvert.INSTANCE.convert(updateReqVO);
        quickCombinationActivityMapper.updateById(updateObj);
    }

    @Override
    public void deleteQuickCombinationActivity(Long id) {
        // 校验存在
        validateQuickCombinationActivityExists(id);
        // 删除
        quickCombinationActivityMapper.deleteById(id);
    }

    private QuickCombinationActivityDO validateQuickCombinationActivityExists(Long id) {
        QuickCombinationActivityDO activityDO = quickCombinationActivityMapper.selectById(id);
        if (activityDO == null) {
            throw exception(QUICK_COMBINATION_ACTIVITY_NOT_EXISTS);
        }

        return activityDO;
    }

    @Override
    public QuickCombinationActivityDO getQuickCombinationActivity(Long id) {
        return quickCombinationActivityMapper.selectById(id);
    }

    @Override
    public List<QuickCombinationActivityDO> getQuickCombinationActivityList(Collection<Long> ids) {
        if (CollUtil.isEmpty(ids)) {
            return ListUtil.empty();
        }
        return quickCombinationActivityMapper.selectBatchIds(ids);
    }

    @Override
    public List<QuickCombinationActivityDO> getQuickCombinationActivityListBySpuId(Long id){
        return quickCombinationActivityMapper.selectList(QuickCombinationActivityDO::getSpuId, id);
    }

    @Override
    public PageResult<QuickCombinationActivityDO> getQuickCombinationActivityPage(QuickCombinationActivityPageReqVO pageReqVO) {
        return quickCombinationActivityMapper.selectPage(pageReqVO);
    }

    @Override
    public List<QuickCombinationActivityDO> getQuickCombinationActivityList(QuickCombinationActivityExportReqVO exportReqVO) {
        return quickCombinationActivityMapper.selectList(exportReqVO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void closeCombinationActivityById(Long id) {
        // 校验活动是否存在
        QuickCombinationActivityDO activity = validateQuickCombinationActivityExists(id);
        if (activity.getStatus().equals(1)) {
            throw exception(COMBINATION_ACTIVITY_STATUS_DISABLE_NOT_UPDATE);
        }

        // 关闭活动
        quickCombinationActivityMapper.updateById(new QuickCombinationActivityDO().setId(id)
                .setStatus(1));
    }

    @Override
    public List<QuickCombinationProductDO> getCombinationProductListByActivityIds(Collection<Long> activityIds){
        return quickCombinationProductMapper.selectListByActivityIds(activityIds);
    }

    @Override
    public QuickCombinationProductDO validateQuickCombination(Long userId, Long activityId, Long skuId, Integer count){
        QuickCombinationActivityDO activityDO = getQuickCombinationActivity(activityId);

        if(activityDO == null){
            throw exception(QUICK_COMBINATION_ACTIVITY_NOT_EXISTS);
        }

        // 校验活动是否开启
        if (ObjUtil.equal(activityDO.getStatus(), CommonStatusEnum.DISABLE.getStatus())) {
            throw exception(QUICK_COMBINATION_ACTIVITY_STATUS_DISABLE);
        }

        // 校验活动开始时间
        if (afterNow(activityDO.getStartTime())) {
            throw exception(QUICK_COMBINATION_RECORD_FAILED_TIME_NOT_START);
        }

        // 校验活动结束时间
        if (beforeNow(activityDO.getEndTime())) {
            throw exception(QUICK_COMBINATION_RECORD_FAILED_TIME_END);
        }

        QuickCombinationProductDO productDO = quickCombinationProductMapper.selectOne(new LambdaQueryWrapper<QuickCombinationProductDO>()
                .eq(QuickCombinationProductDO::getActivityId, activityId)
                .eq(QuickCombinationProductDO::getSkuId, skuId));

        if(productDO == null){
            throw exception(QUICK_COMBINATION_PRODUCT_NOT_EXISTS);
        }

        // 4.2 校验 sku 是否存在
        ProductSkuRespDTO sku = productSkuApi.getSku(skuId);
        if (sku == null) {
            throw exception(QUICK_COMBINATION_JOIN_ACTIVITY_PRODUCT_NOT_EXISTS);
        }
        // 4.3 校验库存是否充足
        if (count > sku.getStock()) {
            throw exception(QUICK_COMBINATION_ACTIVITY_UPDATE_STOCK_FAIL);
        }

        return productDO;
    }

}
